﻿using System;
using System.Collections.Generic;
using System.Text;

namespace XoLib.Manager
{
    /// <summary>
    ///   TemplateRegistrator
    /// </summary>
    public abstract class TemplateRegistrator<T>
    {

        /// <summary>
        ///  Store All Class
        /// </summary>
        public Dictionary<string, Dictionary<ushort, T>> DicClass { get; private set; }


        /// <summary>    
        ///  Constructor
        /// </summary>
        public  TemplateRegistrator()
        {
            DicClass = new Dictionary<string, Dictionary<ushort, T>>();
        }

        /// <summary>
        /// <para>
        /// <param name="key">string</param>
        /// <param name="Code">ushort</param>
        /// <param name="store">T</param>
        /// </para>
        ///   TryGetValue
        /// </summary>
        public bool TryGetValue(string key, ushort Code, out T store)
        {
            Dictionary<ushort, T> dic = null;

            if (!DicClass.TryGetValue(key, out dic))
            {
                store = default(T);
                return false;
            }
            return dic.TryGetValue(Code, out store);
        }


        /// <summary>
        /// <para>
        /// <param name="ClassType">Type</param>
        /// </para>
        ///   Register Class IClass
        /// </summary>
        public void RegisterClass(Type ClassType)
        {
            int Code = -1;
            string Name = null;
            var attributes = ClassType.GetCustomAttributes(typeof(IClass), false);
            if (attributes.Length == 1)
            {
                Code = ((IClass)attributes[0]).Code;
                Name = ((IClass)attributes[0]).ToString();
            }
            else
                return;

            if (!(Code >= ushort.MinValue && Code <= ushort.MaxValue))
                return;

            T data;
            if( !(data = AddInDic( ClassType,  Code,  Name)).Equals(default(T)))
            {
                Dictionary<ushort, T> dic = null;

                if (!DicClass.TryGetValue(Name, out dic))
                    DicClass.Add(Name, new Dictionary<ushort, T>());

                if (!DicClass.TryGetValue(Name, out dic))
                    return;

                DicClass[Name].Add(Convert.ToUInt16(Code), data);
            }
       
        }


        /// <summary>
        /// <para>
        /// <param name="ClassType">Type</param>
        /// <param name="Code">int</param>
        /// <param name="Name">string</param>
        /// </para>
        ///   MakeTheRegister
        /// </summary>
        internal abstract T AddInDic(Type ClassType, int Code, string Name);

        /// <summary>
        /// <para>
        /// <param name="ClassTypes">Type[]</param>
        /// </para>
        ///   Register Class IClass
        /// </summary>
       public void RegisterClass(Type[] ClassTypes)
        {
            foreach (Type pType in ClassTypes)
            {
                RegisterClass(pType);
            }
        }



    }
}
